<?php

namespace App\Console\Commands\Cruise;

use App\Jobs\Cruise\SelfCheck\TaskExpiredJob;
use App\Models\Clickhouse\Guanyuan\GyDailyDeliveryReportCHModel;
use App\Models\Cruise\CruiseCheckDetailModel;
use App\Models\Cruise\CruiseCheckSelfDetailModel;
use App\Models\Cruise\CruiseCheckSelfTaskCompanyMappingModel;
use App\Models\Cruise\CruiseCheckSelfTaskModel;
use App\Models\Cruise\CruiseCheckTaskModel;
use App\Models\Cruise\CruiseTemplateModel;
use App\Models\Shop\ShopModel;
use App\Service\Cruise\Check\CruiseOrderService;
use Carbon\Carbon;
use Carbon\CarbonInterface;
use Exception;
use Illuminate\Console\Command;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\DB;

class CruiseCheckSelfTaskGenerateScheduleCommand extends Command
{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'cruise:checkSelfTaskGenerateSchedule';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = '自检任务定时生成';

    /**
     * Create a new command instance.
     *
     * @return void
     */
    public function __construct()
    {
        parent::__construct();
    }

    /**
     * Execute the console command.
     *
     * @return int
     * @throws Exception
     */
    public function handle(): int
    {
        CruiseCheckSelfTaskModel::query()
                                ->with("cruiseCheckSelfTaskCompanyMappingsRel")
                                ->where("status", CruiseCheckSelfTaskModel::STATUS_ON)
                                ->where("taskStartTime", "<=", time())
                                ->where("taskEndTime", ">=", time())
                                ->where("templateType", CruiseTemplateModel::TYPE_8)
                                ->chunkById(100, function (Collection $collection) {
                                    $collection->each(function (CruiseCheckSelfTaskModel $checkSelfTaskModel) {
                                        switch ($checkSelfTaskModel->templateType) {
                                            case CruiseTemplateModel::TYPE_8:
                                                self::generateTaskDetail_8($checkSelfTaskModel);
                                                break;
                                        }
                                    });
                                });

        return 0;
    }

    /**
     * 门店自检任务详情创建
     *
     * @param CruiseCheckSelfTaskModel $checkSelfTaskModel
     * @throws Exception
     */
    public static function generateTaskDetail_8(CruiseCheckSelfTaskModel $checkSelfTaskModel)
    {
        // todo 生成关联任务数据闭包方法
        $generateCruiseOrderRelFunc = function (
            CruiseCheckSelfTaskModel $checkSelfTaskModel,
            ShopModel $shopModel,
            CruiseTemplateModel $cruiseTemplateModel
        ) {
            try {
                // todo 获取任务详情模型类
                $checkSelfDetailModel = self::getTaskDetail(
                    $checkSelfTaskModel,
                    $shopModel->id
                );

                if (!$checkSelfDetailModel->cruiseOrderId) {
                    // todo 未关联任务 新建任务详情
                    $template = CruiseTemplateModel::query()->where("id", $checkSelfTaskModel->templateId)->first();
                    if (!$template) {
                        throw new Exception("模版获取失败");
                    }

                    // 重写任务类执行周期时间
                    switch ($cruiseTemplateModel->sysTemplate) {
                        case CruiseTemplateModel::SYS_TEMPLATE_SELF_OPEN:
                            // 营业前×小时至营业后×小时
                            list($startDateTime, $endDateTime) = $shopModel->getFormatBusinessTime();
                            $checkSelfTaskModel->executeStartHis = $startDateTime->clone()
                                                                                 ->subHours($checkSelfTaskModel->executeStartBefore)->timestamp;
                            $checkSelfTaskModel->executeEndHis   = $startDateTime->clone()
                                                                                 ->addHours($checkSelfTaskModel->executeEndAfter)->timestamp;
                            break;
                        case CruiseTemplateModel::SYS_TEMPLATE_SELF_CLOSE:
                            // 营业前×小时至营业后×小时
                            list($startDateTime, $endDateTime) = $shopModel->getFormatBusinessTime();

                            if($startDateTime > $endDateTime){
                                $checkSelfTaskModel->executeStartHis = $endDateTime->clone()->addDay()
                                                                                   ->subHours($checkSelfTaskModel->executeStartBefore)->timestamp;
                                $checkSelfTaskModel->executeEndHis   = $endDateTime->clone()->addDay()
                                                                                   ->addHours($checkSelfTaskModel->executeEndAfter)->timestamp;
                            }else{
                                $checkSelfTaskModel->executeStartHis = $endDateTime->clone()
                                                                                   ->subHours($checkSelfTaskModel->executeStartBefore)->timestamp;
                                $checkSelfTaskModel->executeEndHis   = $endDateTime->clone()
                                                                                   ->addHours($checkSelfTaskModel->executeEndAfter)->timestamp;
                            }

                            break;
                        case CruiseTemplateModel::SYS_TEMPLATE_SELF_WEEK:
                            // 周六0点至周一凌晨3点
                            $checkSelfTaskModel->executeStartHis = \Illuminate\Support\Carbon::now()
                                                                                             ->startOfWeek()->timestamp;
                            $checkSelfTaskModel->executeEndHis   = \Illuminate\Support\Carbon::now()
                                                                                             ->next(CarbonInterface::MONDAY)
                                                                                             ->startOfDay()
                                                                                             ->addHours(3)->timestamp;
                            break;
                        case CruiseTemplateModel::SYS_TEMPLATE_SELF_MONTH:
                            // 月末5天至月初第一天凌晨3点
                            $checkSelfTaskModel->executeStartHis = \Illuminate\Support\Carbon::now()
                                                                                             ->endOfMonth()
                                                                                             ->subDays(4)->startOfDay()->timestamp;
                            $checkSelfTaskModel->executeEndHis   = \Illuminate\Support\Carbon::now()
                                                                                             ->endOfMonth()
                                                                                             ->addHours(3)->timestamp;
                            break;
                    }

                    try {
                        DB::beginTransaction();

                        // todo 添加任务表
                        $cruiseCheckTask = CruiseCheckTaskModel::add(
                            $checkSelfTaskModel->name,
                            $checkSelfTaskModel->templateId,
                            $checkSelfTaskModel
                        );

                        // 回写任务执行时间
                        CruiseCheckSelfDetailModel::query()->where("id", $checkSelfDetailModel->id)->update([
                            "executeStartTime" => $cruiseCheckTask->startTime,
                            "executeEndTime"   => $cruiseCheckTask->endTime,
                        ]);

                        $sysTemplate = (int)CruiseTemplateModel::query()
                                                               ->where('id', $cruiseCheckTask->templateId)
                                                               ->value('sysTemplate');

                        $cruiseOrder = CruiseOrderService::addTaskDb(
                            "",
                            $shopModel->id,
                            $cruiseCheckTask->id,
                            0,
                            '',
                            $sysTemplate,
                            CruiseCheckDetailModel::CHECK_TYPE_COMMON,
                            $checkSelfTaskModel->templateId
                        );

                        // todo 更新门店自检任务详情关联任务id
                        CruiseCheckSelfDetailModel::query()
                                                  ->where('id', $checkSelfDetailModel->id)
                                                  ->update([
                                                      'cruiseOrderId'  => $cruiseOrder->id
                                                  ]);

                        DB::commit();
                    } catch (Exception $exception) {
                        DB::rollBack();
                        throw new $exception;
                    }

                    // 任务自动过期job写入
                    (new TaskExpiredJob($checkSelfDetailModel->id, $cruiseCheckTask->endTime - time()))->expiredDispatch();


                    $cruiseCheckDetails = CruiseCheckDetailModel::query()->where("orderId", $cruiseOrder->id)->first();
                    // todo 更新门店自检任务详情 cruise_check_details.id
                    CruiseCheckSelfDetailModel::query()
                                              ->where('id', $checkSelfDetailModel->id)
                                              ->update([
                                                  'checkDetailsId' => attributeGet($cruiseCheckDetails, "id", 0)
                                              ]);
                }
            } catch (Exception $exception) {
                logException(
                    vsprintf(
                        "%s 生成行任务失败 [ cruise_check_self_task.id : %s ] [ shopId : %s ] [ error : %s ]",
                        [
                            "门店自检任务定时生成",
                            $checkSelfTaskModel->id,
                            $shopModel->id,
                            $exception->getMessage()
                        ]
                    ),
                    $exception,
                    $checkSelfTaskModel->toArray(),
                    true,
                    true
                );
            }
        };

        $cruiseTemplateModel = CruiseTemplateModel::query()
                                                  ->where("id", $checkSelfTaskModel->templateId)
                                                  ->select(["id", "name", "desc", "type", "sysTemplate"])
                                                  ->first();

        //todo 遍历对应所有活跃门店生成记录
        ShopModel::query()->where(
            "status", ShopModel::STATUS_OK
        )->when(
            !checkEnv("qa"),
            function ($query) {
                $query->whereIn(
                // todo 获取活跃门店
                    "shopCode",
                    GyDailyDeliveryReportCHModel::getActivityShopLists(7)
                );
            }
        )->when(
        //todo 对应部分门店 增加查询条件
            $checkSelfTaskModel->shopScope == CruiseCheckSelfTaskModel::SHOP_SCOPE_PART,
            function ($query) use ($checkSelfTaskModel) {
                $query->whereIn(
                    "id",
                    $checkSelfTaskModel->cruiseCheckSelfTaskCompanyMappingsRel->pluck("shopId")->toArray()
                );
            }
        )->chunkById(
            500,
            function (Collection $collection) use (
                $checkSelfTaskModel,
                $generateCruiseOrderRelFunc,
                $cruiseTemplateModel
            ) {
                $collection->each(function (ShopModel $shopModel) use (
                    $checkSelfTaskModel,
                    $generateCruiseOrderRelFunc,
                    $cruiseTemplateModel
                ) {
                    $generateCruiseOrderRelFunc(
                        $checkSelfTaskModel,
                        $shopModel,
                        $cruiseTemplateModel
                    );
                });
            }
        );
    }


    /**
     * 获取任务详情
     *
     * @param CruiseCheckSelfTaskModel $checkSelfTaskModel
     * @param int $shopId
     * @return Builder|Model|object|null
     * @throws Exception
     */
    public static function getTaskDetail(
        CruiseCheckSelfTaskModel $checkSelfTaskModel,
        int $shopId
    ) {
        list($ruleCycleStart, $ruleCycleEnd) = $checkSelfTaskModel->getRuleCycle();

        $checkSelfDetailModel = CruiseCheckSelfDetailModel::query()
                                                          ->where("createdAt", ">=", $ruleCycleStart)
                                                          ->where("createdAt", "<=", $ruleCycleEnd)
                                                          ->where("shopId", $shopId)
                                                          ->where("taskId", $checkSelfTaskModel->id)
                                                          ->first();

        if (empty($checkSelfDetailModel)) {
            $checkSelfDetailModel = CruiseCheckSelfDetailModel::query()->create(
                [
                    "shopId"       => $shopId,
                    "taskId"       => $checkSelfTaskModel->id,
                    "templateType" => $checkSelfTaskModel->templateType,
                    "sysTemplate"  => $checkSelfTaskModel->sysTemplate,
                    "date"         => Carbon::now()->format('Ymd'),
                    "createdAt"    => time(),
                    'status'       => CruiseCheckSelfDetailModel::STATUS_1
                ]
            );
        }

        return $checkSelfDetailModel;
    }
}
